/* @flow */

import type Watcher from './watcher'
import { remove } from '../util/index'
import config from '../config'

let uid = 0

/**
 * dep是可观察的，可以有多个订阅它的指令。
 * 
 * Dep 类可以收集依赖（ Watcher ），删除依赖，或者向依赖发送通知
 * Watcher 是一个中介角色，数据发生变化时通知它，然后它再通知其他地方
 */ 
export default class Dep {
  // 静态属性 target，这是全局唯一 Watcher
  // 在同一时间只能有一个全局的 Watcher 被计算，它自身属性 subs 也是 Watcher 数组
  static target: ?Watcher;
  id: number;
  subs: Array<Watcher>;

  constructor () {
    this.id = uid++
    this.subs = []
  }

  addSub (sub: Watcher) {
    this.subs.push(sub)
  }

  removeSub (sub: Watcher) {
    remove(this.subs, sub)
  }

  depend () {
    if (Dep.target) {
      Dep.target.addDep(this)
    }
  }

  notify () {
    // stabilize the subscriber list first
    const subs = this.subs.slice()
    if (process.env.NODE_ENV !== 'production' && !config.async) {
      //如果未运行异步，则不会在调度程序中对子进行排序
      //我们现在需要对它们进行排序，以确保它们正确触发
      //命令 
      subs.sort((a, b) => a.id - b.id)
    }
    // 遍历所有的 subs，也就是 Watcher 的实例数组，然后调用每一个 watcher 的 update 方法
    for (let i = 0, l = subs.length; i < l; i++) {
      subs[i].update()
    }
  }
}

// The current target watcher being evaluated.
// This is globally unique because only one watcher
// can be evaluated at a time.
Dep.target = null
const targetStack = []

export function pushTarget (target: ?Watcher) {
  targetStack.push(target)
  Dep.target = target
}

/**
 * 把 Dep.target 恢复成上一个状态，因为当前 vm 的数据依赖收集已经完成，那么对应的渲染Dep.target 也需要改变
 */
export function popTarget () {
  targetStack.pop()
  Dep.target = targetStack[targetStack.length - 1]
}
